#!/usr/bin/python
# -*-coding:utf-8-*-
import pandas as pd
import datetime
from time import sleep
from time import time
import multiprocessing as mp

try:
    try:
        from zg_factor_analysis_module.utils import loadFile
        from zg_factor_analysis_module.utils import writeToFile
    except:
        from .utils import loadFile
        from .utils import writeToFile
except:
    from support_functions import loadFile
    from support_functions import writeToFile

def add_minute(dt, interval=120):
    next_time = pd.to_datetime(dt) + pd.Timedelta(minutes=interval)
    return next_time.strftime('%Y-%m-%d %H:%M:%S')

def transform_datetime(datetime_str='2018-11-02 17:09:00'):
    return datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')

def run_schedule(run_func, datetime_str, is_sleep=True, verbose=True, **params):
    while True:
        now_time = datetime.datetime.now()

        if now_time > transform_datetime(datetime_str):
            run_func(**params)

            break

        if is_sleep:
            if verbose: print('sleeping...')
            sleep(30)


def run_signal_schedule(run_func, interaction_file_path, process_id, is_sleep=True, verbose=True, **params):
    if 'longest_waiting_time' in params.keys():
        longest_waiting_time = params['longest_waiting_time']
    else:
        longest_waiting_time = 24 * 60 * 60

    while True:
        st = time()
        run_schedule = loadFile(interaction_file_path)
        sleep(2)

        if run_schedule[process_id]:
            print('process - %d starts...' % (process_id))

            run_func(**params)

            # TODO - 发送信号，表示下一个进程可以运行
            run_schedule[process_id+1] = True

            writeToFile(run_schedule, interaction_file_path)

            print('process - %d done!\n' % (process_id))
            break

        if is_sleep:
            if verbose: print('sleeping...')
            sleep(30)

        et = time()

        # TODO - N小时之后自动结束进程
        if et-st > longest_waiting_time:
            print('waiting %.4f hours and no execution, so break!' % ((et-st)/(60*60)))
            break

def multiprocess_wrap(factor_analysis_func, run_time_schedule_list, **kwargs):
    '''
    通过运行时间列表来运行多进程因子分子的函数

    :param factor_analysis_func: 因子分析函数
    :param run_time_schedule_list: 运行时间列表，其中时间格式为：%Y-%m-%d %H:%M:%S
    :param kwargs: 因子分析函数的入参, key为0到N-1, N表示run_time_schedule_list的长度，对应不同时间运行的程序参数, 必须输入，否则会报错
    N = len(run_time_schedule_list)
    kwargs = {
    '0': ... ,
    '1': ... ,
    '2': ... ,

    ...

    'N-1': ... ,
    }

    '''
    Process_jobs = []

    mp.freeze_support()

    ####
    # TODO - 开始分析
    for id in range(len(run_time_schedule_list)):
        dt = run_time_schedule_list[id]
        params = kwargs[str(id)]

        ###
        p = mp.Process(target=run_schedule, args=(factor_analysis_func,
                                                  dt,
                                                  True,
                                                  False),
                       kwargs=params)

        p.daemon = True
        Process_jobs.append(p)

    print(Process_jobs)
    for job in Process_jobs:
        job.start()

    for job in Process_jobs:
        job.join()


def multiprocess_wrap_by_signal(run_func_dict,
                                interaction_file_path,
                                signal_ids_list,
                                is_sleep=True,
                                verbose=False,
                                **kwargs):
    '''
    通过运行时间列表来运行多进程因子分子的函数

    :param run_func: 因子分析函数
    :param signal_ids_list: 运行id列表, 元素为0,1,2,....
    :param kwargs: 因子分析函数的入参, key为0到N-1, N表示run_time_schedule_list的长度，对应不同时间运行的程序参数, 必须输入，否则会报错
    N = len(run_time_schedule_list)
    kwargs = {
    '0': ... ,
    '1': ... ,
    '2': ... ,

    ...

    'N-1': ... ,
    }

    '''
    Process_jobs = []

    mp.freeze_support()

    ####
    # TODO - 开始分析
    # for id in run_func_dict:
    for id in signal_ids_list:
        params = kwargs[str(id)]
        run_func = run_func_dict[str(id)]

        ###
        p = mp.Process(target=run_signal_schedule, args=(run_func,
                                                         interaction_file_path,
                                                         id,
                                                         is_sleep,
                                                         verbose),
                       kwargs=params)

        p.daemon = True
        Process_jobs.append(p)

    print(Process_jobs)
    for job in Process_jobs:
        job.start()

    for job in Process_jobs:
        job.join()



